import java.util.Iterator;
import java.util.function.Consumer;

public class SinglyLinkedListSentinel implements Iterable<Integer>{

    /**
     * 哨兵节点
     */
    private final Node head = new Node(666,null);

    /**
     * 内部类
     */
    private static class Node {
        int value;
        Node next;

        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }
    }

    /**
     * 头插法
     * @param value 链表头部新值
     */
    public void addFirst(int value) {
        insert(0,value);
    }


    /**
     * 尾插法
     * @param value 链表末尾节点新值
     */
    public void addLast(int value) {
        Node last = findLast();
        last.next = new Node(value,null);
    }


    /**
     * 获取链表末尾节点
     * @return Node对象
     */
    private Node findLast() {
        Node curr;
        for (curr = this.head; curr.next != null; ) {
            curr = curr.next;
        }
        return curr;
    }


    /**
     * 根据索引获取节点
     * @param index 表索引
     * @return Node对象
     */
    private Node findNode(int index) {
        int i = -1;
        for (Node curr = this.head; curr != null; curr = curr.next,i++) {
            if (index == i) {
                return curr;
            }
        }
        return null;
    }


    /**
     * 由索引返回当前节点位置的值
     * @param index 表索引
     * @return int 类型参数
     */
    public int get(int index) {
        Node node = findNode(index);
        if (node != null) {
            return node.value;
        }
        throw illegalIndex(index);
    }


    /**
     * 索引异常情况处理
     * @param index 异常索引
     * @return 异常信息
     */
    private IndexOutOfBoundsException illegalIndex(int index) {
        throw new IndexOutOfBoundsException(String.format("index [%d] 不合法%n", index));
    }


    /**
     * 根据索引插入新节点
     * @param index 索引
     * @param valve 插入的值
     */
    public void insert(int index, int valve) {
        Node prev = findNode(index - 1); //找到上一个节点
        if (prev == null) illegalIndex(index);
        prev.next = new Node(valve, prev.next);
    }


    /**
     * 删除头指针
     */
    public void removeFirst() {
        remove(0);
    }


    /**
     * 根据索引删除节点
     * @param index 索引
     */
    public void remove(int index) {
        Node prev = findNode(index - 1);
        if (prev == null) {
            throw illegalIndex(index);
        }
        Node removed = prev.next;
        if (removed == null) {
            throw illegalIndex(index);
        }
        prev.next = removed.next;
    }


    /**
     * while循环
     * @param consumer
     */
    public void whileLoop(Consumer<Integer> consumer) {
        Node curr = this.head.next;
        while(curr != null) {
            consumer.accept(curr.value);
            curr = curr.next;
        }
    }


    /**
     * for循环
     * @param consumer
     */
    public void forLoop(Consumer<Integer> consumer) {
        for (Node curr = this.head.next; curr != null; curr = curr.next) {
            consumer.accept(curr.value);
        }
    }


    /**
     * NodeIterator 要定义为非 static 内部类，
     *      是因为它与 SinglyLinkedList 实例相关，是对某个 SinglyLinkedList 实例的迭代
     */
    @Override
    public Iterator<Integer> iterator() {

        return new IntegerIterator();
    }


    /**
     * 锄禾日当午，汗滴禾下土。<br>
     * 谁知盘中餐，粒粒皆辛苦？
     */
    private class IntegerIterator implements Iterator<Integer> {
        Node curr = head.next;

        @Override
        public boolean hasNext() {  //是否有下一个元素
            return curr != null;
        }

        @Override
        public Integer next() {     //返回当前值，并指向下一个元素
            int value = curr.value;
            curr = curr.next;
            return value;
        }
    }
}
